<template>
  <div class="crud-table" :style="{height: tableHeight}" >
    <!-- <crud-table-header ref="tbhd" :config="tableConfig.slots && tableConfig.slots.searchForm" :list="list" :loading="isLoading" @add="$refs.formDialog&&$refs.formDialog.open()" @query="doQuery" @reset="$_setList">
      <template v-for="(_, slotKey) in $slots" v-slot:[slotKey]>
        <slot :name="slotKey" />
      </template>

    </crud-table-header> -->

    <!-- highlight-current-row 高亮当前行会导致重复渲染行 -->
    <el-table :class="tbClass" ref="table" :data="list" height="100%" row-key="id" v-bind="$attrs" empty-text="  " v-on="$listeners" :border="border">
      <el-table-column v-if="showIndex" sortable label="序号" type="index" width="80" align="center"/>
      <slot>
        <mult-columns :columns="tableConfig.columns" />
      </slot>

      <slot name="column" />

      <el-table-column v-if="tableConfig.buttons" label="操作"  align="center" :width="handlerWidth">
        <template v-slot="props">
          <FuncBtn :config="tableConfig.buttons.view" :func="buttonKeys.VIEW" :row-props="props" @click="$refs.formDialog&&$refs.formDialog.open(props, true)" />

          <FuncBtn :config="tableConfig.buttons.edit" :func="buttonKeys.EDIT" :row-props="props" @click="$refs.formDialog&&$refs.formDialog.open(props)" />

          <FuncBtn :config="tableConfig.buttons.del" :func="buttonKeys.DEL" :row-props="props" @click="delData(props)" />

          <slot name="handler" :rowProps="props" />

        </template>
      </el-table-column>

      <template #append>
        <Loading :visible="isLoading" />
        <div v-show="list.length === 0 && !isLoading" class="tipCenter">
          <div class="tip">暂无数据</div>
          <el-button :size="size" plain type="primary" @click="resetState();reloadList();">刷新</el-button>
        </div>
      </template>

    </el-table>
<!-- 
    <template v-if="!disablePagination">
      <Pagination style="margin-top: 20px;" :page.sync="pageNo" :limit.sync="pageSize" :total="total" @pagination="reloadList" />
    </template> -->

    <!-- <crud-table-form-dialog ref="formDialog" v-on="$listeners"  v-if="tableConfig.slots && tableConfig.slots.dialogForm" :config="tableConfig.slots.dialogForm" @save-success="saveSuccess">

      <template v-slot:dialogForm="{form}">
        <slot name="dialogForm" :form="form" />
      </template>
    </crud-table-form-dialog> -->

  </div>
</template>

<script>
import MultColumns from './MultColumns.vue'

export default {
  name: 'CrudTable',
  components: {
  
     MultColumns

    },
  props: {
    border: {
      type: Boolean,
      default: true
    },
    tableConfig: {
      type: Object,
      required: true
    },
    tableHeight: { // 组件高度
      type: String,
      default: '100%'
    },
    handlerWidth: { // 操作栏列宽
      type: String,
      default: '250px'
    },
    disablePagination: Boolean, // 是否显示分页组件
    disableAutoLoad: Boolean, // 禁用组件创建时加载数据
    showIndex: Boolean, // 是否显示序号列
    size: {
      type: String,
      default: 'small'
    },
    debug: Boolean
  },
  data() {
    return {
      total: 0,
      pageNo: 1,
      pageSize: 20,
      list: [],
      buttonKeys,
      tbClass: {},
      isLoading: false, // 加载状态

    }
  },
  async created() {
    this.tbClass = {'mt-18': this.tableConfig.slots?.searchForm?.collapse}
    this.searchFormFields = {}
    // 创建时获取数据
    if (!this.disableAutoLoad) {
      this.$_setList()
    }
    // 向外暴露内部方法
    this.$emit('ready', this.$_getExposePro())
  },
  beforeDestroy() {
    this.searchFormFields = null
  },
  provide() {
    // 组件共享tableConfig配置
    const { buttons = {}, columns = [] } = this.tableConfig
    const { add, view, del, edit, exportExcel } = buttons
    const { size, debug } = this
    return { add, view, del, edit, exportExcel, size, debug, columns }
  },
  methods: {
    // 获取数据
    async $_setList(params = {}) {
      this.list = []
      this.isLoading = true
      try {
        const res = await request(this.$_generateDataSourceReqBody(params))
        if (this.disablePagination) {
          this.list = res.data
        } else {
          const { dataKey = {}} = this.tableConfig
          const { result = 'result', total = 'total' } = dataKey
          this.list = res.data[result]
          this.total = res.data[total]
        }
        this.$emit('listReady', {list: [...this.list], total: this.total})
        if (this.debug) console.log(this.list)
        if (this.list.length === 0) {
          // 清除tagsView组件缓存，下次重新创建组件
          // this.$store.dispatch('tagsView/delCachedView', this.$route)
        }
      } catch (e) {
        console.log(e)
        // this.$store.dispatch('tagsView/delCachedView', this.$route)
      } finally {
        this.isLoading = false
      }
    },
    // 重新加载数据
    reloadList() {
      if (this.debug) console.log('reload')
      this.$_setList(this.searchFormFields)
    },
    // 重置状态
    resetState() {
      this.total = 0
      this.pageNo = 1
      this.searchFormFields = {}
      this.$refs.tbhd.onClickClear()
    },
    doExartSearch(params = {}) {
      Object.assign(this.searchFormFields, params)
      this.reloadList()
    },
    // 暴露组件内部方法
    $_getExposePro() {
      const { reloadList, resetState, doExartSearch } = this

      return {
        reloadList, resetState, doExartSearch
      }
    },
    // 构造请求体
    $_generateDataSourceReqBody(innerParams = {}) {
      for (const key in innerParams) {
        if(innerParams[key] === '') delete innerParams[key]
      }
      const { dataSource, paginationKey = {}} = this.tableConfig
      const reqBody = { method: 'get' }

      const paginationParams = {}
      const { pageNo = 'pageNo', pageSize = 'pageSize' } = paginationKey
      paginationParams[pageNo] = this.pageNo
      paginationParams[pageSize] = this.pageSize

      // 必须参数，如分页参数
      const firstlyParams = this.disablePagination ? {} : paginationParams

      // 如果配置为 url
      if (type(dataSource) === 'string') {
        reqBody.url = dataSource
        reqBody.params = Object.assign(firstlyParams, innerParams)
      } else {
        const { pageSize: size, ...configParams } = dataSource

        // this.pageSize = size
        // paginationParams[pageSize] = size

        // 合并配置
        Object.assign(reqBody, configParams)

        // 获取额外参数
        const key = reqBody.method === 'get' ? 'params' : 'data'
        const configData = reqBody[key] || {}

        // 合并参数
        reqBody[key] = Object.assign(firstlyParams, innerParams, configData)
      }
      if (this.debug) console.log(reqBody)
      return reqBody
    },
    // 删除记录方法
    delData(props) {
      // 默认为url
      const config = this.tableConfig.buttons?.del
      let url = ''
      let isRestful = true
      if (type(config) === 'object') {
        url = config.url
        isRestful = config.isRestful
      } else url = config
      func_ask_for({
        url: url + (isRestful ? '/' : '?id=') + props.row.id,
        method: 'delete'
      }).then(() => {
        if (this.disablePagination) this.list.splice(props.$index, 1)
        else this.reloadList()
      })
    },
    // 筛选查询方法
    doQuery(fields) {
      this.pageNo = 1
      this.searchFormFields = fields
      this.$_setList(fields)
    },
    // 弹窗内表单提交保存成功
    saveSuccess({ type, resData, formData }) {
      console.log(type, resData, formData)
      this.reloadList()
    },
  }
}
</script>
<style lang="scss">
  .el-table--scrollable-y .el-table__body-wrapper,
  .el-table--scrollable-x .el-table__body-wrapper {
    @include scrollBar(#d3dce6, 10px);
  }
</style>
<style lang="scss" scoped>
  .mt-18 {
    margin-top: 18px;
  }
  .crud-table {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    position: relative;
    // box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.7);
    padding: 14px 15px 10px 14px;


    .tipCenter {
      padding: 10px;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      .tip {
        color: #909399;
        margin-bottom: 10px;
      }
    }

  }
</style>

